package cn.turboinfo.fuyang.api.domain.mini.usecase.login;

import cn.turboinfo.fuyang.api.domain.common.service.SmsService;
import cn.turboinfo.fuyang.api.domain.common.service.user.SysUserService;
import cn.turboinfo.fuyang.api.domain.common.service.user.UserLoginService;
import cn.turboinfo.fuyang.api.domain.common.service.user.UserTypeRelService;
import cn.turboinfo.fuyang.api.domain.common.usecase.AbstractUseCase;
import cn.turboinfo.fuyang.api.domain.mini.service.session.MiniSessionService;
import cn.turboinfo.fuyang.api.entity.common.enumeration.sms.SmsType;
import cn.turboinfo.fuyang.api.entity.common.enumeration.user.LoginNameType;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.SysUser;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.SysUserCreator;
import cn.turboinfo.fuyang.api.entity.common.pojo.user.UserLogin;
import cn.turboinfo.fuyang.api.entity.mini.pojo.session.MiniSession;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import net.sunshow.toolkit.core.base.enums.EnableStatus;
import nxcloud.foundation.core.validation.constraints.MobileNumber;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotEmpty;
import java.util.List;
import java.util.UUID;

/**
 * 手机短信验证码登录
 *
 * @author sunshow
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class MiniLoginBySmsCodeUseCase extends AbstractUseCase<MiniLoginBySmsCodeUseCase.InputData, MiniLoginBySmsCodeUseCase.OutputData> {

    private final SmsService smsService;

    private final SysUserService sysUserService;

    private final UserLoginService userLoginService;

    private final UserTypeRelService userTypeRelService;

    private final MiniSessionService miniSessionService;

    @Override
    protected OutputData doAction(InputData inputData) {
        // 验证登录
        String loginName = inputData.getLoginName();
        String smsCode = inputData.getSmsCode();

        // 验证短信验证码
        smsService.verifyCode(SmsType.RegisterOrLogin, loginName, smsCode);

        // 从登录方式检查用户是否存在
        Long userId;
        List<UserLogin> loginList = userLoginService.findByLoginNameAndLoginNameType(loginName, LoginNameType.PHONE_NUM);
        if (loginList.isEmpty()) {
            log.error("用户不存在, 自动创建, loginName={}", loginName);
            // 创建用户
            SysUserCreator.Builder builder = SysUserCreator.builder()
                    .withMobile(loginName)
                    .withUsername(loginName)
                    .withStatus(EnableStatus.ENABLED);
            SysUser sysUser = sysUserService.save(builder.build(), null);

            //创建关联
            userTypeRelService.createConsumerRel(sysUser.getId());

            userId = sysUser.getId();
        } else {
            // 用户已存在, 检查是否已有消费者关联
            userId = loginList.get(0).getUserId();
            if (!userTypeRelService.hasConsumerRel(userId)) {
                // 创建相应的关联
                userTypeRelService.createConsumerRel(userId);
            }
        }

        // 登录成功后创建 Session
        MiniSession session = MiniSession
                .builder()
                .userId(userId)
                .build();

        String token = UUID.randomUUID().toString();
        miniSessionService.save(token, session);

        return OutputData.builder()
                .token(token)
                .build();
    }

    @EqualsAndHashCode(callSuper = true)
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Builder
    public static class InputData extends AbstractUseCase.InputData {

        @NotEmpty(message = "登录名不能为空")
        @MobileNumber
        private String loginName;

        @NotEmpty(message = "短信验证码不能为空")
        private String smsCode;

    }

    @Getter
    @Setter
    @Builder
    public static class OutputData extends AbstractUseCase.OutputData {

        /**
         * 登录成功的会话令牌
         */
        private String token;

    }
}
